package com.cloudream.core.repository;

import com.cloudream.core.bo.PagerBo;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;

@Repository
public class BaseRepository<T, PK extends Serializable> extends HibernateDaoSupport {

    public Session getSession() {
        return super.getSessionFactory().openSession();
    }

    @Resource(name = "sessionFactory")    //为父类HibernateDaoSupport注入sessionFactory的值
    public void setSuperSessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }


    public void delete(T entity) {
        super.getHibernateTemplate().delete(entity);
    }


    public void deleteById(Class entityClass, PK id) {
        super.getHibernateTemplate().delete(findById(entityClass, id));

    }

    public Long save(T entity) {
        return (Long) super.getHibernateTemplate().save(entity);

    }

    public void update(T entity) {
        super.getHibernateTemplate().update(entity);
    }

    public void saveorupdate(T entity) {
        super.getHibernateTemplate().saveOrUpdate(entity);
    }

    public int update(String hql, Object[] params) {
        Query query = super.getSessionFactory().openSession().createQuery(hql);
        for (int i = 0; i < params.length; i++) {
            query.setParameter(i, params[i]);
        }
        return query.executeUpdate();
    }


    public List<T> findAll(Class entityClass) {

        return super.getHibernateTemplate().loadAll(entityClass);
    }

    public List<T> findAll(Class entityClass, String hql, Object[] params, int start, int limit) {
        Query query = this.getSession().createQuery(hql);
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        if (start != 0 && limit != 0) {
            query.setFirstResult(start).setMaxResults(limit);
        }
        return query.list();
    }

    public List<T> findByExample(T entity) {
        return super.getHibernateTemplate().findByExample(entity);
    }

    public List<T> findByHql(String hql, Object[] params) {
        Query query = this.getSession().createQuery(hql);
        if (null != params && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        return query.list();
    }

    public T findById(Class entityClass, PK id) {
        return (T) super.getHibernateTemplate().get(entityClass, id);
    }

    public List<T> findByProperty(Class entityClass, String propertyName, Object value) {
        String queryString = "from " + entityClass.getName() + " as model where model." + propertyName + "=?";
        return (List<T>) this.getHibernateTemplate().find(queryString, value);
    }


    //分页使用
    public List<T> findByPage(Class<T> entityClass, int start, int limit) {
        Query query = this.getSession().createQuery("select o from " + entityClass.getName() + " o");
        query.setFirstResult(start).setMaxResults(limit);
        return query.list();
    }


    public T getTotalCount(Class entityClass) {

        return (T) this.getSession().createQuery("select count(o) from " + entityClass.getName() + " o").uniqueResult();
    }

    public T getPageCount(String hql, Object[] params) {
        Query query = this.getSession().createQuery(hql);
        if (null != params && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        return (T) query.list();
    }


    public PagerBo<T> getPage(int currentPage, int limit, List<Criterion> crts, Class entityClass) {
        Criteria c = this.getSession().createCriteria(entityClass);
        for (Criterion crt : crts) {
            c.add(crt);
        }
        c.setProjection(Projections.rowCount());
        int totalRecord = Integer.valueOf(c.uniqueResult().toString());
        c.setProjection(null);
        c.setFirstResult((limit) * (currentPage - 1));
        c.setMaxResults(limit);
        c.addOrder(Order.desc("uid"));
        List<T> list = c.list();
        PagerBo<T> page = new PagerBo<T>();
        page.setPage(currentPage);
        page.setLimit(limit);
        page.setTotal(totalRecord);
        page.setList(list);
        return page;
    }

}
